#ifndef _THREAD_HPP_
#define _THREAD_HPP_

#include <thread>
#include <iostream>
#include <pthread.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>

namespace threadModlue
{
    static uint32_t number = 1;
    template <typename T>
    class Thread
    {
        using func_t = std::function<void(T)>;

    public:
        Thread(func_t func, T data) : _isDetach(false),
                                      _isRunning(false),
                                      _tid(0),
                                      res(nullptr),
                                      _func(func),
                                      _data(data)
        {
            _name = "thread" + std::to_string(number++);
        }
        void Detach()
        {
            if (_isDetach) //|| !_isRunning)
                return;
            if (_isRunning)
                pthread_detach(_tid); // 已经运行，手动分离
            EnableDetach();
        }

        void EnableRunning()
        {
            _isRunning = true;
        }

        static void *Routine(void *arg)
        {
            Thread<T> *thread = static_cast<Thread<T> *>(arg);
            thread->EnableRunning();
            if (thread->_isDetach)
            {
                thread->Detach();
            }

            thread->_func(thread->_data); // 调用传入的函数对象
            return nullptr;
        }

        //  void *Routine(void *arg)  { }
        // 属于类内部函数，不能直接作为pthread_create的回调函数 ,默认包含this指针
        // 需要定义为静态函数，或者使用友元函数
        bool Start()
        {
            if (_isRunning)
                return false;
            int n = pthread_create(&_tid, nullptr, Routine, this);
            if (n != 0)
            {
                std::cerr << "pthread_create error: " << n << std::endl;
                return false;
            }
            EnableRunning();
            if (_isDetach)
                Detach();
            std::cout << _name << " has been started with tid: " << _tid << std::endl;
            return true;
        }
        bool stop()
        {
            if (_isRunning)
            {
                int x = pthread_cancel(_tid);
                if (x != 0)
                {
                    std::cerr << "pthread_cancel error: " << x << std::endl;
                    return false;
                }
                _isRunning = false;
                std::cout << _name << " has been stop" << std::endl;
                return true;
            }
            return false;
        }
        void Join()
        {
            if (_isDetach)
            {
                std::cout << _name << " is detached, cannot join." << std::endl;
                return;
            }
            int x = pthread_join(_tid, &res);
            if (x != 0)
            {
                std::cerr << "pthread_join error: " << x << std::endl;
                return;
            }
            std::cout << _name << " exit code: " << reinterpret_cast<intptr_t>(res) << std::endl;
            //  _isRunning = false;
        }
        ~Thread() {}

    private:
        pthread_t _tid;
        std::string _name;
        bool _isDetach;
        bool _isRunning;
        void *res;
        func_t _func;
        T _data;
        void EnableDetach()
        {
            std::cout << _name << " has been detached." << std::endl;
            _isDetach = true;
        }
    };
} // namespace thread

#endif // !_THREAD_HPP_
